/**
* @copyright Copyright (c) 2022-2023 Grab GEO IoT Team
* @file unit_struct.h
* @author wenzhu.tu
* @version 0.1
* @date 2023-04-23
<<<<<<< HEAD
* @brief persistence com
=======
* @brief persistence com, not thread safe
>>>>>>> fce35a03da8b8eb1530708c7cf62c40c49150153
*/
#ifndef PERSISTENCE_COM_H
#define PERSISTENCE_COM_H

/******************************* Includes ********************************/
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>

#ifdef __cplusplus
extern "C"
{
#endif
/******************************* Macros ******************************/
#define PERSIST_TAG "[PER-M] "
#define PERSIST_E(fmt, ...) do {printf(PERSIST_TAG); printf(fmt, ##__VA_ARGS__); printf("\n");} while(0)
#define PERSIST_W(fmt, ...) do {printf(PERSIST_TAG); printf(fmt, ##__VA_ARGS__); printf("\n");} while(0)
#define PERSIST_I(fmt, ...) do {printf(PERSIST_TAG); printf(fmt, ##__VA_ARGS__); printf("\n");} while(0)
#define PERSIST_D(fmt, ...) do {printf(PERSIST_TAG); printf(fmt, ##__VA_ARGS__); printf("\n");} while(0)

#define MAX_UNIT_DATA_SIZE   (1024)

#define MAGIC_START   (0x644499EC)
#define MAGIC_END     (0x644499ED)

#define PERSIST_INC_INDEX(X, MAX_PERSIST_SIZE)  X = (X+1)%MAX_PERSIST_SIZE
#define PERSIST_DEC_INDEX(X, MAX_PERSIST_SIZE)  X = (X+MAX_PERSIST_SIZE-1)%MAX_PERSIST_SIZE
#define PERSIST_IS_FULL(handle)   (handle->header.read_index == (handle->header.write_index + 1)%handle->header.max_persist_size ? 1 : 0)
#define PERSIST_IS_EMPTY(handle)  (handle->header.read_index == handle->header.write_index ? 1 : 0)

#define PERSIST_VERSION (0)
/******************************* Typedef ******************************/
typedef enum PERSIST_MODE
{
    PERSIST_MODE_RAM,
    PERSIST_MODE_FILE,
    PERSIST_MODE_MAX
}PERSIST_MODE_e;

typedef struct usr_data
{
    int  id;        // identifier, customer use
    char data[MAX_UNIT_DATA_SIZE];
}usr_data_t;

typedef struct unit_struct
{
    int magic_start;// MAGIC_START  
    int is_valid;   // 0 invalid 1 valid    
    usr_data_t usrdata; 
    int magic_end;  // MAGIC_END
}unit_struct_t;

typedef struct persistence_head
{
    int magic_start;  //MAGIC_START
    int version;      //start from 0
    int read_index;
    int write_index;
    int max_persist_size;
    PERSIST_MODE_e mode;
    int magic_end;    //MAGIC_END
}persistence_head_t;

typedef struct persistence_handle
{
    persistence_head_t header;
    int fd;
    unit_struct_t *unit_array;
}persistence_handle_t;

typedef enum PERSIST_DUMP_TYPE
{
<<<<<<< HEAD
     PERSIST_DUMP_ALL,
=======
    PERSIST_DUMP_HEADER,
    PERSIST_DUMP_ALL,
>>>>>>> fce35a03da8b8eb1530708c7cf62c40c49150153
     
}PERSIST_DUMP_TYPE_e;
/******************************* Variables ******************************/

/******************************* Functions ******************************/

/**
 * @brief persistence handle init
 * @param max_persist_size[in] record count 
 * @param file_name[in] mode == PERSIST_MODE_FILE
 * @param mode[in] PERSIST_MODE_e 
 * @return persistence_handle_t* NULL is errod
 */
persistence_handle_t *persistence_com_init(int max_persist_size, char *file_name,  PERSIST_MODE_e mode);

/**
 * @brief persistence handle deinit
 * @param handle[in] persistence_handle_t
 * @return int 0
 */
int persistence_com_deinit(persistence_handle_t *handle);

/**
 * @brief push record data
 * @param handle[in] persistence_handle_t 
 * @param data 
 * @param datalen 
 * @param id 
 * @return int -1 error  -2 full 0 success
 */
int persistence_com_push(persistence_handle_t *handle, char *data, int datalen, int id);

/**
<<<<<<< HEAD
 * @brief get record data
=======
 * @brief only get last record data, not delete
>>>>>>> fce35a03da8b8eb1530708c7cf62c40c49150153
 * @param handle[in] persistence_handle_t  
 * @param usr_data*
 * @return int -1 error -2 empty 0 success
 */
int persistence_com_get(persistence_handle_t *handle, usr_data_t *usr_data);

/**
<<<<<<< HEAD
 * @brief pop record data
=======
 * @brief pop record data(delete last one)
>>>>>>> fce35a03da8b8eb1530708c7cf62c40c49150153
 * @param handle[in] persistence_handle_t  
 * @return int -1 error 0 success
 */
int persistence_com_pop(persistence_handle_t *handle);

/**
<<<<<<< HEAD
 * @brief dump persistence info
 * @return int -1 error 0 success
 */
int persistence_dump(PERSIST_DUMP_TYPE_e dump_type);
=======
 * @brief dump persistence handle info
 * @return int -1 error 0 success
 */
int persistence_dump(persistence_handle_t *handle, PERSIST_DUMP_TYPE_e dump_type);
>>>>>>> fce35a03da8b8eb1530708c7cf62c40c49150153
#ifdef __cplusplus
}
#endif

#endif

/******************************* End of file ******************************/